package com.sf.osms.dep.processor.handler;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import com.sf.osms.dep.domain.Agent;
import com.sf.osms.dep.domain.AgentConfig;
import com.sf.osms.dep.domain.AgentFileMap;
import com.sf.osms.dep.domain.Router;
import com.sf.osms.dep.domain.RouterProblemRecord;
import com.sf.osms.dep.domain.RouterTmp;
import com.sf.osms.dep.processor.exception.ExceptionConstants;
import com.sf.osms.dep.processor.exception.RouterException;
import com.sf.osms.dep.processor.handler.convert.ConverterChain;
import com.sf.osms.dep.processor.handler.dynamicexcjava.DynamicExecUtil;
import com.sf.osms.dep.processor.model.EventModel;
import com.sf.osms.dep.processor.util.CollectionUtil;
import com.sf.osms.dep.processor.util.DateUtil;
import com.sf.osms.dep.processor.util.ExceptionUtils;
import com.sf.osms.dep.processor.util.ReflectUtils;
import com.sf.osms.dep.processor.util.RouterConstants;
import com.sf.osms.dep.processor.util.VerifyRouter;

/**
 * 处理逻辑抽象类
 * @author sfhq1405
 *
 * @param <T> 需要处理的对象
 */
public abstract class AbstractEventHandler<T> implements EventHandler<T,Router> {
	
	private ConverterChain converterChain = new ConverterChain(); //转化器链
	private final static Logger logger = Logger.getLogger(AbstractEventHandler.class);
	
	public AbstractEventHandler() {
		registerConverters(converterChain);
	}

	@Override
	public EventModel<T, Router> handle(EventModel<T,Router> eventModel,
			Agent agentInfo) throws RouterException {
		
		if(null == eventModel || null == agentInfo){
			return null;
		}
		//得到需要进行处理的原始数据集合
		List<T> orginalRecords = eventModel.getRecordList();
		
		//创建处理成为Router的集合
		List<Router> correctRouter = new ArrayList<Router>();
		eventModel.setCorrectRouter(correctRouter);
		
		//错误处理的集合
		List<RouterProblemRecord> errorRecords = new ArrayList<RouterProblemRecord>();
		eventModel.setErrorEventRecord(errorRecords);
				
		if(!CollectionUtil.isEmpty(orginalRecords)){
			for (int i = 0 ; i < orginalRecords.size() ; i++) {
				T record =  orginalRecords.get(i);
				try {
					eventModel.setLineNum(i+1);
					convertToRouter(eventModel,record,agentInfo); //原始数据转换为Router
				} catch (Exception ex){
					logger.error("处理" + eventModel.getFile().getName() + "中的数据:" + getRecordStr(record,agentInfo) + ",出现异常");
					logger.error(ExceptionUtils.getExceptionStackString(ex));
					ExceptionUtils.buildRouterProblemRecord(eventModel, agentInfo, 
							new RouterException(ExceptionConstants.NOT_TRANSFER_ROUT_CODE,getRecordStr(record, agentInfo)));
				}
				
			}
		}
		
		return eventModel;
	}

	/**
	 * 将解析出来的原始数据转化为Router
	 * @param eventModel
	 * @param record
	 * @param agentInfo
	 * @throws RouterException
	 */
	public void convertToRouter(EventModel<T,Router> eventModel, T record,
			Agent agentInfo) throws RouterException{
		
		AgentFileMap parseRules = agentInfo.getAgentFileMap();
		if(null == parseRules){
			return;
		}
		String mapRules = parseRules.getMapRule();
		Map<String,String> routerFieldAndStr = null;
	
		if(RouterConstants.AGENT_FILE_SPLIT_NUM.equals(parseRules.getColumnSep())){
			Map<String,String> newMapRules = CollectionUtil.formatRuleToMap(mapRules); //字段对应规则,必须是一一对应
			if(record instanceof String[]){
				String lineStr = ((String[]) record)[0];
				if(StringUtils.isNotBlank(lineStr)){
					routerFieldAndStr = CollectionUtil.getFieldAndValueMap(newMapRules,lineStr);
				}
			}
			
		}else{
			Map<String,String> newMapRules = CollectionUtil.formatRuleToMap(mapRules); //字段对应规则,必须是一一对应
			Map<String, String> fieldValues = CollectionUtil.transferObjectToMap(record); //字段--字段值（Map形式）
			//进行原始数据Groovy脚本的加工
			if(null != agentInfo.getGif()){
				try {
					agentInfo.getGif().handleSimgleOrginalRouter(fieldValues);
				} catch (Exception e) {
					logger.error("groovy脚本处理map集合出现异常:" + ExceptionUtils.getExceptionStackString(e));
				}
				
			}
			//得到Router表中属性和属性对应的String类型的值
			routerFieldAndStr =CollectionUtil.getFileldAndValueMap(newMapRules, fieldValues);
		}
		
		Router router = new Router();
		
		//为路由信息设置行号
		router.setLineNum(eventModel.getLineNum());
		
		//进行各个属性的处理
		converterChain.setIntial(); //进行转化责任链条的初始化
		converterChain.convert(router, routerFieldAndStr, agentInfo, eventModel, converterChain);
		
		//条件表达式处理
		List<AgentConfig> agentCofigs = agentInfo.getAgentCofigs();
		if(!CollectionUtil.isEmpty(agentCofigs) && agentCofigs.get(0).getConfigType() == 2){
			//条件表达式的映射
			String[] sfCodess = null;
			try {
				sfCodess = getDynamicSfCode(agentInfo, router);
			} catch (Exception e1) {
				logger.error("******代理：" + agentInfo.getName() + ",处理文件："
						+ eventModel.getFile().getAbsolutePath() + "," + "eventCode条件表达式转化出现异常******" + e1);
				router.addFailReasonList(ExceptionConstants.DYNAMIC_JAVA_COMPILE_ERROR_CODE);
				logger.error(ExceptionUtils.getExceptionStackString(e1));
			}
			//进行节点的转换
			if(null != sfCodess){
				Date barDate = router.getBarDate();
				Date barTime = router.getBarTime();
				for(int a=0;a<sfCodess.length;a++){
					String sfCode = sfCodess[a];
					
					if(a == 0){
						String[] sfCodes = sfCode.split(",");
						Integer eventCode = null;
						for (int i = 0; i < sfCodes.length; i++) {
							if (i == 0) {
								try {
									eventCode = Integer.valueOf(sfCodes[i].trim());
									router.setEventCode(eventCode);
									
								} catch (Exception e) {
									logger.error("******代理：" + agentInfo.getName() + ",处理文件："
											+ eventModel.getFile().getAbsolutePath() + "," + "eventCode转化出现异常******" + e);
									router.addFailReasonList(ExceptionConstants.HANDLE_EVENT_CODE_ERROR_CODE);
									logger.error(ExceptionUtils.getExceptionStackString(e));
								}

							}
							if (i == 1) {
								try {
									Integer resonCode = Integer.valueOf(sfCodes[i].trim());
									router.setReasonCode(resonCode);
								} catch (Exception e) {
									logger.error("******代理：" + agentInfo.getName() + ",处理文件："
											+ eventModel.getFile().getAbsolutePath() + ","
											+ "reasonCode（失败原因节点节点）字段转化出现异常******");
									router.addFailReasonList(ExceptionConstants.HANDLE_RESON_CODE_ERROR_CODE);
									logger.error(ExceptionUtils.getExceptionStackString(e));
								}
							}
						}
						
						//进行bar时间的特殊处理
						if(RouterConstants.AGENT_BAR_DATE_HANDLE_LIST.contains(agentInfo.getName()) || (router.getBarDate() == null && router.getBarTime() == null)){
							handleSpecialBarDate(router,agentInfo);
							
						}
						
					
						
						//路由检查和加入正确集合
						checkRouter(router,eventModel,agentInfo,record);
						
						//进行路由分类插入
						if((StringUtils.isBlank(router.getSfWaybill()) && StringUtils.isBlank(router.getAgentWaybill()))
							|| (StringUtils.isNotBlank(router.getSfWaybill()) && null == router.getEventCode())){
							
							
								ExceptionUtils.buildRouterProblemRecord(eventModel,agentInfo,new RouterException(router.getFailReason(),getRecordStr(record, agentInfo)));
							
						}else{
							saveRouter(eventModel,router,agentInfo);
						}

						
					}else {
						//分支重新实例化
						Router routerNew = new Router();
						try {
							
							//BeanUtils.copyProperties(routerNew, router);
							ReflectUtils.copyProperties(routerNew, router);
						} catch (Exception e) {
							logger.error("路由分裂，copy路由相同信息出现异常");
						}
						String[] sfCodes = sfCode.split(",");
						Integer eventCode = null;
						for (int i = 0; i < sfCodes.length; i++) {
							if (i == 0) {
								try {
									eventCode = Integer.valueOf(sfCodes[i].trim());
									routerNew.setEventCode(eventCode);
								
								} catch (Exception e) {
									logger.error("******代理：" + agentInfo.getName() + ",处理文件："
											+ eventModel.getFile().getAbsolutePath() + "," + "eventCode转化出现异常******" + e);
									router.addFailReasonList(ExceptionConstants.HANDLE_EVENT_CODE_ERROR_CODE);
									logger.error(ExceptionUtils.getExceptionStackString(e));
								}

							}
							if (i == 1) {
								try {
									Integer resonCode = Integer.valueOf(sfCodes[i].trim());
									routerNew.setReasonCode(resonCode);
									
								} catch (Exception e) {
									logger.error("******代理：" + agentInfo.getName() + ",处理文件："
											+ eventModel.getFile().getAbsolutePath() + ","
											+ "reasonCode（失败原因节点节点）字段转化出现异常******");
									router.addFailReasonList(ExceptionConstants.HANDLE_RESON_CODE_ERROR_CODE);
									logger.error(ExceptionUtils.getExceptionStackString(e));
								}
							}
						}
						
						//进行bar时间的特殊处理
						if(RouterConstants.AGENT_BAR_DATE_HANDLE_LIST.contains(agentInfo.getName()) || (barDate == null && barTime == null)){
							handleSpecialBarDate(routerNew,agentInfo);
							
						}
						
						//路由检查和加入正确集合
						checkRouter(routerNew,eventModel,agentInfo,record);
						//进行路由分类插入
						if((StringUtils.isBlank(router.getSfWaybill()) && StringUtils.isBlank(router.getAgentWaybill()))
								|| (StringUtils.isNotBlank(router.getSfWaybill()) && null == router.getEventCode())){
								
									ExceptionUtils.buildRouterProblemRecord(eventModel,agentInfo,new RouterException(router.getFailReason(),getRecordStr(record, agentInfo)));
								
								
						}else{
							saveRouter(eventModel,routerNew,agentInfo);
						}
					}
				}
			}else{
				router.addFailReasonList(ExceptionConstants.CONDITION_EXPRESS_NO_MAPPING_CODE);
				checkRouter(router, eventModel, agentInfo, record);
				ExceptionUtils.buildRouterProblemRecord(eventModel,agentInfo,new RouterException(router.getFailReason(),getRecordStr(record, agentInfo)));
			}
			
		}else{
			//路由检查
			checkRouter(router,eventModel,agentInfo,record);
			//进行路由分类插入
			if((StringUtils.isBlank(router.getSfWaybill()) && StringUtils.isBlank(router.getAgentWaybill()))
					|| (StringUtils.isNotBlank(router.getSfWaybill()) && null == router.getEventCode())){
					
					ExceptionUtils.buildRouterProblemRecord(eventModel,agentInfo,new RouterException(router.getFailReason(),getRecordStr(record, agentInfo)));
			}else{
				saveRouter(eventModel,router,agentInfo);
			}
		}
	
	}
	private void saveRouter(EventModel<T, Router> eventModel, Router router,Agent agentInfo) {
		
		if(StringUtils.isNotBlank(router.getAgentNetNum())){
			String netNum = agentInfo.getNetNum();
			String[] split = netNum.split(",");
			String[] operators = agentInfo.getOperatorId().split(",");
			if(split != null && split.length >= 2){
				if(router.getAgentNetNum().equals(RouterConstants.JPPOST_NET_NUM_MAP_ONE)){
					router.setNetNum(split[0]);
					router.setOperatorId(operators[0]);
				}else if(router.getAgentNetNum().equals(RouterConstants.JPPOST_NET_NUM_MAP_TWO)){
					router.setNetNum(split[1]);
					if(operators.length >= 2){
						router.setOperatorId(operators[1]);
					}else{
						router.setOperatorId(operators[0]);
					}
					
				}else{
					if(StringUtils.isBlank(router.getFailReason())){
						ExceptionUtils.buildRouterProblemRecord(eventModel,agentInfo,
								new RouterException(ExceptionConstants.AGENT_NET_NUM_NOT_MAPPING_CODE,getRecordStr(eventModel.getRecordList().get(router.getLineNum()), agentInfo)));
					}else{
						ExceptionUtils.buildRouterProblemRecord(eventModel,agentInfo,
								new RouterException(router.getFailReason() + "," +ExceptionConstants.AGENT_NET_NUM_NOT_MAPPING_CODE,getRecordStr(eventModel.getRecordList().get(router.getLineNum()), agentInfo)));
					}
					return;
				}
			}
			
		}
		
		if(StringUtils.isBlank(router.getSfWaybill()) && StringUtils.isNotBlank(router.getAgentWaybill())){
			RouterTmp routerTmp = new RouterTmp();
			try {
				//BeanUtils.copyProperties(routerTmp,router);
				ReflectUtils.copyProperties(routerTmp, router);
			} catch (Exception e) {
				logger.error("复制需要handerover处理的Router信息异常");
				logger.error(ExceptionUtils.getExceptionStackString(e));
			}
			eventModel.getNeedHandleRouter().add(routerTmp);
			return;
		}
		
		//进行xml中特殊节点的分裂
		if("xml".equalsIgnoreCase(agentInfo.getAgentFileMap().getFileSuffix())){
			if(router.getEventCode() == 14){
				Router routerNew = new Router();
				ReflectUtils.copyProperties(routerNew, router);
				routerNew.setEventCode(44);
				//进行44节点特殊化处理
				if(StringUtils.isNotBlank(routerNew.getAgentWaybill())){
					routerNew.setExtendAttach3(routerNew.getAgentWaybill());
				}
				eventModel.getCorrectRouter().add(routerNew);
			}
		}
		
		//进行加入之前的Groovy脚本的处理
		if(null != agentInfo.getGif()){
			try {
				agentInfo.getGif().handleSimgleRouter(router);
			} catch (Exception e) {
				logger.error("groovy脚本处理router出现异常:" + ExceptionUtils.getExceptionStackString(e));
			}
		
		}
		eventModel.getCorrectRouter().add(router);
		
	}

	//进行原始记录的还原
	protected abstract String getRecordStr(T record,Agent agentInfo) ;
	
	//进行Converter转换器的注册
	public abstract void registerConverters(ConverterChain converterChain);
	
	//进行路由检查
	private void checkRouter(Router router,EventModel<T, Router> eventModel,Agent agentInfo,T record){
		
		//进行代理节点的测试
		if(RouterConstants.AGENT_DATA_TEST_FLAG == agentInfo.getAgentFlag()){
			eventModel.getCorrectRouter().add(router);
			return;
		}
		
		if(!CollectionUtil.isEmpty(router.getFailReasonList())){
			List<String> resonList = router.getFailReasonList();
			String failReason = "";
			for (String str:resonList) {
				failReason = failReason + "," + str;
			}
			router.setFailReason(failReason.substring(1));
			router.setStatus(1); //异常状态的设置
		}else{
			try {
				VerifyRouter.commonVertify(router);
				router.setStatus(2);
			} catch (RouterException e) {
				router.setFailReason(e.getExceptionCode()); //进行异常代码的设置
				router.setStatus(1); //异常状态的设置
			}
			
		}
	}
	
	//bar枪时间具有逻辑性的
	private void handleSpecialBarDate(Router router,Agent agentInfo){
		Integer ec = router.getEventCode();
		List<AgentConfig> agentCofigs2 = agentInfo.getAgentCofigs();
		String agentExpress = null;
		for (AgentConfig agentConfig : agentCofigs2) {
			String sfCodeNew = agentConfig.getSfCode();
			if(sfCodeNew.equalsIgnoreCase(ec+"")){
				agentExpress = agentConfig.getAgentCode();
			}
		}
		
		
		if(StringUtils.isNotEmpty(agentExpress)){
			Map<String, String> gt = router.gt();
			
			Set<String> keySet = new HashSet<String>();
			keySet.addAll(gt.keySet());
			Iterator<String> iterator = keySet.iterator();
			while (iterator.hasNext()) {
				String next = iterator.next();
				if(!agentExpress.contains(next)){
					iterator.remove();
				}
			}
			
			for(String key:keySet){
				String str = gt.get(key);
				if(str.length() >= 8){
					try {
						Date formatDate = DateUtil.formatDate(str);
						router.setBarDate(formatDate);
					} catch (Exception e) {
						router.addFailReasonList(ExceptionConstants.HANDLE_BAR_DATE_ERROR_CODE);
						logger.error("******代理：" + agentInfo.getName() +",处理文件：" +
								"," + "barDate（把枪日期）字段转化出现异常******");
						logger.error(ExceptionUtils.getExceptionStackString(e));
					}
					
				}else{
					try {
						Date formatTime = DateUtil.formatTime(str);
						router.setBarTime(formatTime);
					} catch (Exception e) {
						router.addFailReasonList(ExceptionConstants.HANDLE_BAR_TIME_ERROR_CODE);
						logger.error("******代理：" + agentInfo.getName() +",处理文件："+
								"," + "barTime（把枪时间）字段转化出现异常******");
						logger.error(ExceptionUtils.getExceptionStackString(e));
					}
					
				}
			}
		}
	}
	
	private static String[] getDynamicSfCode(Agent agentInfo,Router router) throws Exception{
		List<AgentConfig> agentCofigs = agentInfo.getAgentCofigs();
		StringBuffer methodContent = new StringBuffer();
		methodContent.append("String retVal = \"\";");
		for (AgentConfig agentConfig : agentCofigs) {
			if(2 == agentConfig.getConfigType()){
				String sfCodeMap = agentConfig.getSfCode();
				
				methodContent.append(agentConfig.getAgentCode());
				methodContent.append("retVal = retVal + \"" + sfCodeMap + "@" + "\";");
			}
		}
		methodContent.append("return retVal;");
		String sfCode = null;
		String methodSrc = methodContent.toString();
		if(StringUtils.isNotBlank(methodSrc)){
			String dynamicClassName = agentInfo.getName() + "DynamicRule";
			StringBuilder src = new StringBuilder();
			  src.append("import java.util.Map;");
			  src.append("import java.util.HashMap;");
			  src.append("public class " + dynamicClassName + " {");
		      src.append("public String getSfCode(" + Router.class.getName() + " router) {");
		      src.append(methodSrc);
		      src.append("}");
		      src.append("}");
		    Object instance  =  DynamicExecUtil.getDynamicObject(dynamicClassName, src.toString());
			Method method = instance.getClass().getMethod("getSfCode", Router.class);
			sfCode = (String)method.invoke(instance, router);
			
		}
		if(StringUtils.isEmpty(sfCode)){
			return null;
		}
		sfCode = sfCode.substring(0, sfCode.length()-1);		
		return sfCode.split("@");
	}

	public static void main(String[] args) throws Exception{
		Router routerNew = new Router();
		Router router = new Router();
		router.setBarDate(DateUtil.formatDate("20160502"));
		router.setBarTime(DateUtil.formatTime("165150"));
		
		BeanUtils.copyProperties(routerNew, router);
		System.out.println(routerNew);
	}
}
